package com.tqjc.system.core.pipeline.service;

import cn.hutool.core.collection.CollUtil;
import com.tqjc.system.common.constant.AddTaskConstant;
import com.tqjc.system.common.entity.BO.AddBusinessTaskInfo;
import com.tqjc.system.common.entity.BO.MoreTaskMaterialBO;
import com.tqjc.system.common.entity.BO.SingleTaskMaterialBO;
import com.tqjc.system.common.entity.BO.TaskMaterialBO;
import com.tqjc.system.common.enums.CarEnum;
import com.tqjc.system.common.enums.CarPLCInfoEnum;
import com.tqjc.system.common.enums.TankCarNoEnum;
import com.tqjc.system.common.enums.TaskStatusEnum;
import com.tqjc.system.core.pipeline.BusinessProcess;
import com.tqjc.system.core.pipeline.ProcessContext;
import com.tqjc.system.core.pipeline.thread.AddTaskGuardThread;
import com.tqjc.system.core.pipeline.thread.CarDoingAddTaskThread;
import com.tqjc.system.core.pipeline.thread.CarDoingSingleAddTaskThread;
import com.tqjc.system.core.pipeline.util.AddTaskUtil;
import com.tqjc.system.core.pipeline.util.ScanUtils;
import com.tqjc.system.core.threadpool.ThreadPoolManager;
import com.tqjc.system.system.entity.SysAddPrimaryTaskEntity;
import com.tqjc.system.system.service.SysAddDetailTaskService;
import com.tqjc.system.system.service.SysAddPrimaryTaskService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author 86195
 * @version 1.0
 * @description 天车执行抓料任务
 * @date 2023/10/18 9:28
 */
@Slf4j
@Service
public class CarExecuteTaskAction implements BusinessProcess<AddBusinessTaskInfo> {

    @Autowired
    private SysAddDetailTaskService addDetailTaskService;

    @Autowired
    private SysAddPrimaryTaskService primaryTaskService;

    @Override
    public void process(ProcessContext<AddBusinessTaskInfo> context) {
        AddBusinessTaskInfo processModel = context.getProcessModel();
        context.setBreakFlag(true);
        boolean flag = processModel.isFlag();
        String taskId = processModel.getTaskId();
        String workingSpanNo = processModel.getWorkingSpanNo();
        log.info("加料任务taskId：{},对工作跨:{}的任务物料排序开始", taskId, workingSpanNo);
        //工作跨
        //获取排序任务物料  未完成的物料  升序
        List<TaskMaterialBO> workingMaterialList = addDetailTaskService.sortSpanTaskMaterialList(workingSpanNo, taskId);
        //槽车号
        String tankCarNo = processModel.getTankCarNo();


        //更新槽车扫描flag
        ScanUtils.updateTankCarFlag(TankCarNoEnum.getEnumByCarNo(tankCarNo),flag);
        //从集合取出排序最小值有排序最大值
        int size = workingMaterialList.size();

        //若集合还存在物料，缓存该集合为后续线程共享变量   key:taskId   value:workingMaterialList
        AddTaskUtil.TASK_WORKING_MATERIAL_MAP.put(taskId, workingMaterialList);

        ScanUtils.updateTankCarFlag(TankCarNoEnum.getEnumByCarNo(tankCarNo),false);

        if (flag) {

            //指定天车干活
            while (workingMaterialList.size() != 0){

                TaskMaterialBO taskMaterialBO = workingMaterialList.get(0);
                workingMaterialList.remove(0);
                CarEnum carEnum = CarEnum.getCarEnumByCarNo(processModel.getCarNo());
                //当前子任务只有一个,派发一台合理的天车  根据任务物料库区位置，选择合适天车
                SingleTaskMaterialBO singleTaskMaterialBO = SingleTaskMaterialBO.builder().taskId(taskId)
                        .workingSpanNo(workingSpanNo).materialNo(taskMaterialBO.getWorkinMaterialNo()).tankCarNo(processModel.getTankCarNo())
                        .carEnum(carEnum).idKey(taskMaterialBO.getIdKey()).areaNum(taskMaterialBO.getAreaNum()).build();
                //异常启动线程干活
                CarDoingSingleAddTaskThread thread = CarDoingSingleAddTaskThread.builder().taskMaterialBO(singleTaskMaterialBO).build();
                thread.setTaskId(taskId);
                String threadKey = CarPLCInfoEnum.getCarNoEnum(workingSpanNo, carEnum.getCarNo()).getMacSN();
                AddTaskConstant.CAR_THREAD_MAP.put(threadKey,thread);
                ThreadPoolManager.getInstance().execute(thread);
                while (true) {
                    if (thread.isTaskFinishFlag()) {
                        AddTaskConstant.CAR_THREAD_MAP.remove(threadKey);
                        log.info("加料任务taskId：{}对工作跨:{}的任务物料排序,单线程干活完成", taskId, workingSpanNo);
                        break;
                    }
                    try {

                        Thread.sleep(3*1000);
                    } catch (Exception e){
                        AddTaskUtil.updateSpanNoStatus(workingSpanNo,AddTaskConstant.SPAN_STATUS_FREE);
                        log.info("单线程休眠出现异常",e);
                        AddTaskUtil.TASK_WORKING_MATERIAL_MAP.remove(taskId);
                        return;
                    }
                }
            }

        }else if(size == 1){
            TaskMaterialBO taskMaterialBO = workingMaterialList.get(0);
            CarEnum carEnum = taskMaterialBO.getAreaIndex() > CarEnum.CAR_NO_2.getIndex() ? CarEnum.CAR_NO_1 : CarEnum.CAR_NO_2;
            //当前子任务只有一个,派发一台合理的天车  根据任务物料库区位置，选择合适天车
            SingleTaskMaterialBO singleTaskMaterialBO = SingleTaskMaterialBO.builder().taskId(taskId)
                    .workingSpanNo(workingSpanNo).materialNo(taskMaterialBO.getWorkinMaterialNo()).tankCarNo(processModel.getTankCarNo())
                    .carEnum(carEnum).idKey(taskMaterialBO.getIdKey()).areaNum(taskMaterialBO.getAreaNum()).build();
            //异常启动线程干活
            CarDoingSingleAddTaskThread thread = CarDoingSingleAddTaskThread.builder().taskMaterialBO(singleTaskMaterialBO).build();
            thread.setTaskId(taskId);
            String threadKey = CarPLCInfoEnum.getCarNoEnum(workingSpanNo, carEnum.getCarNo()).getMacSN();
            AddTaskConstant.CAR_THREAD_MAP.put(threadKey,thread);
            //ThreadPoolManager.getInstance().execute(thread);
            thread.start();
            while (true) {
                if (thread.isTaskFinishFlag()) {
                    AddTaskConstant.CAR_THREAD_MAP.remove(threadKey);
                    log.info("加料任务taskId：{}对工作跨:{}的任务物料排序,单线程干活完成", taskId, workingSpanNo);
                    break;
                }
                try {

                    Thread.sleep(3*1000);
                } catch (Exception e){
                    AddTaskUtil.updateSpanNoStatus(workingSpanNo,AddTaskConstant.SPAN_STATUS_FREE);
                    log.info("单线程休眠出现异常",e);
                    AddTaskUtil.TASK_WORKING_MATERIAL_MAP.remove(taskId);
                    return;

                }
            }


        }else {
            MoreTaskMaterialBO taskMaterialBO1 = MoreTaskMaterialBO.builder().taskId(taskId).test(processModel.getTest())
                    .workingSpanNo(workingSpanNo).tankCarNo(processModel.getTankCarNo()).carEnum(CarEnum.CAR_NO_1).build();
            ReentrantLock lock = new ReentrantLock();
            CarDoingAddTaskThread t1 = CarDoingAddTaskThread.builder().lock(lock).taskMaterialBO(taskMaterialBO1).build();
            MoreTaskMaterialBO taskMaterialBO2 = MoreTaskMaterialBO.builder().taskId(taskId).test(processModel.getTest())
                    .workingSpanNo(workingSpanNo).tankCarNo(processModel.getTankCarNo()).carEnum(CarEnum.CAR_NO_2).build();
            t1.setTaskId(taskId);
            CarDoingAddTaskThread t2 = CarDoingAddTaskThread.builder().lock(lock).taskMaterialBO(taskMaterialBO2).build();
            t2.setTaskId(taskId);
            String t1Key = CarPLCInfoEnum.getCarNoEnum(workingSpanNo, CarEnum.CAR_NO_1.getCarNo()).getMacSN();
            String t2Key = CarPLCInfoEnum.getCarNoEnum(workingSpanNo, CarEnum.CAR_NO_2.getCarNo()).getMacSN();
            String indexT1key = new StringBuilder(workingSpanNo).append("_").append(CarEnum.CAR_NO_1.getCarNo()).toString();
            String indexT2key = new StringBuilder(workingSpanNo).append("_").append(CarEnum.CAR_NO_2.getCarNo()).toString();
            AddTaskConstant.CAR_THREAD_MAP.put(t1Key,t1);
            AddTaskConstant.CAR_THREAD_MAP.put(t2Key,t2);
            AddTaskUtil.updateCarIndex(indexT1key,null);
            AddTaskUtil.updateCarIndex(indexT2key,null);
            AddTaskGuardThread t1GuardThread = AddTaskGuardThread.builder().workingCarKey(indexT1key).otherCarKey(indexT2key)
                    .otherThread(t2).thread(t1).carEnum(CarEnum.CAR_NO_1).build();
            AddTaskGuardThread t2GuardThread = AddTaskGuardThread.builder().workingCarKey(indexT2key)
                    .otherCarKey(indexT1key).otherThread(t1).thread(t2).carEnum(CarEnum.CAR_NO_2).build();
            //守护线程
            ThreadPoolManager.getInstance().execute(t1GuardThread);
            ThreadPoolManager.getInstance().execute(t2GuardThread);
            //启动线程
            t1.start();
            t2.start();
            //ThreadPoolManager.getInstance().execute(t2);
            //ThreadPoolManager.getInstance().execute(t1);



            while (true){
                //两个线程完成工作后，跳出循环
                if(t1.isTaskFinishFlag()  && t2.isTaskFinishFlag()){
                    log.info("加料任务taskId：{}对工作跨:{}的任务物料排序,双线程干活完成",taskId,workingSpanNo);
                    AddTaskConstant.CAR_THREAD_MAP.remove(t1Key);
                    AddTaskConstant.CAR_THREAD_MAP.remove(t2Key);
                    break;
                }
                try {
                    Thread.sleep(1*1000);

                } catch (Exception e){
                    AddTaskUtil.updateSpanNoStatus(workingSpanNo,AddTaskConstant.SPAN_STATUS_FREE);
                    AddTaskUtil.TASK_WORKING_MATERIAL_MAP.remove(taskId);
                    log.error("等待双车联动线程出现异常");
                    return;
                }
            }

        }

        //本跨工作完成，移除该跨
        List<String> taskSpanList = processModel.getTaskSpanList();
        taskSpanList.removeIf( e -> e.equals(workingSpanNo));
        //本跨状态变成空闲状态
        AddTaskUtil.updateSpanNoStatus(workingSpanNo,AddTaskConstant.SPAN_STATUS_FREE);
        if(CollUtil.isEmpty(taskSpanList)){
            //跨区没有值，返回。任务待上料
            boolean isSuccess = addDetailTaskService.allTaskSuccess(taskId);
            String status = isSuccess ? TaskStatusEnum.STATUS_LOAD.getStatus() : TaskStatusEnum.STATUS_ERROR.getStatus();
            Long idKey = Long.valueOf(taskId);
            SysAddPrimaryTaskEntity addPrimaryTask = SysAddPrimaryTaskEntity.builder().idKey(idKey).status(status).build();
            primaryTaskService.updateById(addPrimaryTask);
            AddTaskUtil.TASK_WORKING_MATERIAL_MAP.remove(taskId);
            log.info("加料任务taskId：{},已无跨区信息,所有任务全部执行完成",taskId,workingSpanNo);
            return;
        }
        processModel.setTaskSpanList(taskSpanList);
        context.setBreakFlag(false);
        context.setProcessModel(processModel);

        log.info("加料任务taskId：{}对工作跨的任务物料排序结束",taskId);

    }
}
